package com.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 非公平锁 实现三线程打印 99以内对3 求余
 * 备注：
 * 1.必须算好哪一个线程是最后的结束线程,不然就会死锁，线程不会主动退出，一直在内存中运行
 * 2.获取锁 lock.lock() 必须放在循环体,不然就在获取到锁的线程内 死循环
 * 3.计算好 condition 可以调用await()方法的前提条件 例如：if(currentNum < printLimitNum - 2)
 * 4.为保证不打印99及以上数据，必须加上限制条件 && currentNum < printLimitNum
 * 
 * @author yaojinshan 2018-04-03 15:04
 */
public class ReentrantLockTestPrint {
	static volatile int currentNum = 0;//当前值
	static int printLimitNum = 99;//打印的临界值

	public static void main(String[] args) {
		ThreadGroup group = new ThreadGroup("xx");
		final Lock lock = new ReentrantLock();
		final Condition condition_0 = lock.newCondition();
		final Condition condition_1 = lock.newCondition();
		final Condition condition_2 = lock.newCondition();
		new Thread(group,new Runnable() {
			public void run() {
				while (currentNum < printLimitNum) {
					lock.lock();
					//System.out.println(Thread.currentThread().getName());
					try {
						if (currentNum % 3 == 0  && currentNum < printLimitNum) {
							System.out.println(Thread.currentThread().getName() + "输出：" + currentNum);
							currentNum++;
							condition_1.signal();
							//线程0 最多能打印到 96 超过 96 就不用等待了
							if(currentNum < printLimitNum - 2){
								condition_0.await();
							}
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						lock.unlock();
					}
				}
			};
		}, "--").start();
		
		new Thread(group,new Runnable() {
			public void run() {
				while (currentNum < printLimitNum) {
					lock.lock();
					//System.out.println(Thread.currentThread().getName());
					try {
						if (currentNum % 3 == 1  && currentNum < printLimitNum) {
							System.out.println(Thread.currentThread().getName() + "输出：" + currentNum);
							currentNum++;
							//线程0 最多能打印到 97 超过 97 就不用等待了
							condition_2.signal();
							if(currentNum < printLimitNum - 1){
								condition_1.await();
							}
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						lock.unlock();
					}
				}
			};
		}, "----").start();

		new Thread(group,new Runnable() {
			public void run() {
				while (currentNum < printLimitNum) {
					lock.lock();
					//System.out.println(Thread.currentThread().getName());
					try {
						if (currentNum % 3 == 2 && currentNum < printLimitNum) {
							System.out.println(Thread.currentThread().getName() + "输出：" + currentNum);
							currentNum++;
							if(currentNum < printLimitNum - 2){
								condition_0.signal();
							}
							if(currentNum < printLimitNum - 1){
								condition_2.await();
							}
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					} finally {
						lock.unlock();
					}
				}
			};
		}, "------").start();
	}
}
